﻿using System;
using System.Collections.Generic;
using System.Text;
using TVOnline.Entities;
using EricUtility;

namespace WatchSeriesHelper.Entities
{
    public class TvRageEntry : AbstractLoadingTuple
    {
        private readonly string m_ID;
        private string m_Title;
        private string m_Description;
        private string[] m_Genres;
        private bool m_RunningShow;
        private int m_Runtime;
        private string m_Network;
        private string m_NetworkURL;
        private int[] m_Weekdays;
        private int m_AirHour;
        private int m_AirMin;

        private int m_LastAiredSeason = -1;
        private int m_LastAiredEpisode = -1;
        private DateTime m_LastAiredDate = DateTime.MinValue;

        private int m_NextAiredSeason = -1;
        private int m_NextAiredEpisode = -1;
        private DateTime m_NextAiredDate = DateTime.MinValue;
        private bool m_Broken = false;

        public string ID { get { return m_ID; } }
        public string Title { get { return m_Title; } }
        public string[] Genres { get { return m_Genres; } }
        public bool RunningShow { get { return m_RunningShow; } }
        public string Network { get { return m_Network; } }
        public string NetworkURL { get { return m_NetworkURL; } }
        public int[] Weekdays { get { return m_Weekdays; } }
        public int AirHour { get { return m_AirHour; } }
        public int AirMin { get { return m_AirMin; } }
        public int Runtime { get { return m_Runtime; } }
        public bool Broken { get { return m_Broken; } }
        public string Description { get { return m_Description; } }
        public int LastAiredSeason { get { return m_LastAiredSeason; } }
        public int LastAiredEpisode { get { return m_LastAiredEpisode; } }
        public DateTime LastAiredDate { get { return m_LastAiredDate; } }
        public string SayLastAiredDate { get { return (m_LastAiredDate == DateTime.MinValue) ? "" : String.Format("{0:yyyy}-{0:MM}-{0:dd}", m_LastAiredDate); } }
        public string SayLastAired { get { return (m_LastAiredSeason == -1) ? "" : String.Format("S{0:00}E{1:00}  ({2})", m_LastAiredSeason, m_LastAiredEpisode, SayLastAiredDate); } }
        public int NextAiredSeason { get { return m_NextAiredSeason; } }
        public int NextAiredEpisode { get { return m_NextAiredEpisode; } }
        public DateTime NextAiredDate { get { return m_NextAiredDate; } }
        public string SayNextAiredDate { get { return (m_NextAiredDate == DateTime.MinValue) ? "" : String.Format("{0:yyyy}-{0:MM}-{0:dd}", m_NextAiredDate); } }
        public string SayNextAired { get { return (m_NextAiredSeason == -1) ? "" : String.Format("S{0:00}E{1:00}  ({2})", m_NextAiredSeason, m_NextAiredEpisode, SayNextAiredDate); } }

        public static string URL { get { return "http://www.tvrage.com/shows/"; } }
        protected override void OnLoad()
        {
            try
            {
                if (m_Broken)
                    return;
                string res = EricUtility.Networking.Gathering.GatheringUtility.GetPageSource(URL + m_ID);
                if (res.Contains("There is no webpage for this show, it either never existed or was removed"))
                {
                    m_Broken = true;
                    return;
                }
                m_Title = StringUtility.RemoveHTMLTags(StringUtility.Extract(res, "<h1 class=\"content_title hover_blue\">", "</h1>"));
                m_Description = StringUtility.RemoveHTMLTags(StringUtility.Extract(res, "<div class=\"show_synopsis\">", "</div>"));

                string infoZone = StringUtility.Extract(res, "<b>Classification</b>:", "</div>");
                m_Genres = StringUtility.Extract(infoZone, "<b>Genre</b>: ", "<br>").Replace(" | ", "|").Split('|');
                m_RunningShow = "Canceled/Ended" != StringUtility.Extract(infoZone, "<b>Status</b>: ", "<br>");

                string networkZone = StringUtility.Extract(infoZone, "<b>Network</b>: ", "<br>");
                m_NetworkURL = StringUtility.Extract(networkZone, "<a href='", "'>");
                m_Network = StringUtility.Extract(networkZone, "'>", "</a>");

                string airZone = StringUtility.Extract(infoZone, "<b>Airs</b>: ", "<br>");
                string[] weekdays = airZone.Remove(airZone.IndexOf(" at")).Replace(" ", "").Split(',');
                m_Weekdays = new int[weekdays.Length];
                for (int i = 0; i < weekdays.Length; ++i)
                {
                    m_Weekdays[i] = WeekDay(weekdays[i]);
                }
                m_AirHour = int.Parse(StringUtility.Extract(airZone, " at ", ":")) + (airZone.Contains("pm") ? 12 : 0);
                m_AirMin = int.Parse(StringUtility.Extract(airZone, ":", " "));

                m_Runtime = int.Parse(StringUtility.Extract(infoZone, "<b>Runtime</b>: ", " Minutes"));

                string nextZone = StringUtility.Extract(res, "<h2>Next: ", "</h2>");
                if (nextZone != null)
                {//"\n73: 4x10 -- The Alien Parasite Hypothesis (Dec/09/2010) "
                    string dateZone = nextZone.Substring(nextZone.IndexOf("</a>"));
                    string zone = StringUtility.RemoveHTMLTags(nextZone);
                    string seas = zone.Remove(zone.IndexOf('x'));
                    if (seas != null && int.TryParse(seas, out m_NextAiredSeason))
                    {
                        m_NextAiredEpisode = int.Parse(StringUtility.Extract(zone, "x", " --"));
                    }
                    else
                    {
                        seas = StringUtility.Extract(zone, "S", "-Special");
                        if (seas != null)
                        {
                            m_NextAiredSeason = int.Parse(seas);
                            m_NextAiredEpisode = 99;
                        }
                    }
                    string[] airDate = StringUtility.Extract(dateZone, " (", ") ").Split('/');
                    try
                    {

                        m_NextAiredDate = new DateTime(int.Parse(airDate[2]), Months(airDate[0]), int.Parse(airDate[1]));
                    }
                    catch
                    {
                        m_NextAiredDate = DateTime.MinValue;
                    }

                }
                else
                {
                    m_NextAiredDate = DateTime.MinValue;
                    m_NextAiredEpisode = -1;
                    m_NextAiredSeason = -1;
                }

                string prevZone = StringUtility.Extract(res, "<h2>Prev: ", "</h2>");
                if (prevZone != null)
                {//"\n72: 4x09 -- The Boyfriend Complexity (Nov/18/2010) ');return false;\" onmouseout=\"hideToolTip2();\"  style='width: 100%; padding:0px 0px 0px 0px; font-size: 11px;  height: 13px;white-space: wrap;position: relative;display: block;overflow: hidden;'72: 4x09 -- The Boyfriend Complexity (Nov/18/2010) "
                    string dateZone = prevZone.Substring(prevZone.IndexOf("</a>"));
                    string zone = StringUtility.RemoveHTMLTags(prevZone);
                    string seas = zone.Remove(zone.IndexOf('x'));
                    if (seas != null && int.TryParse(seas, out m_LastAiredSeason))
                    {
                        m_LastAiredEpisode = int.Parse(StringUtility.Extract(zone, "x", " --"));
                    }
                    else
                    {
                        seas = StringUtility.Extract(zone, "S", "-Special");
                        if (seas != null)
                        {
                            m_LastAiredSeason = int.Parse(seas);
                            m_LastAiredEpisode = 99;
                        }
                    }
                    string[] airDate = StringUtility.Extract(dateZone, " (", ") ").Split('/');
                    try
                    {

                        m_LastAiredDate = new DateTime(int.Parse(airDate[2]), Months(airDate[0]), int.Parse(airDate[1]));
                    }
                    catch
                    {
                        m_LastAiredDate = DateTime.MinValue;
                    }
                }
                else
                {
                    m_LastAiredDate = DateTime.MinValue;
                    m_LastAiredEpisode = -1;
                    m_LastAiredSeason = -1;
                }
            }
            catch
            {
                // Well, we will load next time, it was probably a time out !
            }
            
        }
        public TvRageEntry(string id)
        {
            m_ID = id;
        }
        public TvRageEntry(string id, string title, string desc, string[] genres, bool running, string network, string netURL, int week, int hour, int min) :
            this(id)
        {
        }
        public TvRageEntry(string id, string title, string desc, string[] genres, bool running, string network, string netURL, int[] weekdays, int hour, int min, int runtime) :
            this(id)
        {
        }
        public TvRageEntry(string id, string title, string desc, string[] genres, bool running, string network, string netURL, int[] weekdays, int hour, int min, int runtime, int lastAiredS, int lastAiredE, int[] lastAiredD, int nextAiredS, int nextAiredE, int[] nextAiredD) :
            this(id)
        {
            m_Title = title;
            m_Description = desc;
            m_Genres = genres;
            m_RunningShow = running;
            m_Network = network;
            m_NetworkURL = netURL;
            m_Weekdays = weekdays;
            m_AirHour = hour;
            m_AirMin = min;
            m_Runtime = runtime;
            m_Loaded = true;
            m_LastAiredDate = new DateTime(lastAiredD[0], lastAiredD[1], lastAiredD[2]);
            m_LastAiredSeason = lastAiredS;
            m_LastAiredEpisode = lastAiredE;
            m_NextAiredDate = new DateTime(nextAiredD[0], nextAiredD[1], nextAiredD[2]);
            m_NextAiredSeason = nextAiredS;
            m_NextAiredEpisode = nextAiredE;
            m_Loaded = m_NextAiredDate >= DateTime.Now;
        }

        private int WeekDay(string s)
        {
            switch (s)
            {
                case "Sundays": return 1;
                case "Mondays": return 2;
                case "Tuesdays": return 3;
                case "Wednesdays": return 4;
                case "Thursdays": return 5;
                case "Fridays": return 6;
                case "Saturdays": return 7;
            }
            return 0;
        }

        private int Months(string s)
        {
            switch (s)
            {
                case "Jan": return 1;
                case "Feb": return 2;
                case "Mar": return 3;
                case "Apr": return 4;
                case "May": return 5;
                case "Jun": return 6;
                case "Jul": return 7;
                case "Aug": return 8;
                case "Sep": return 9;
                case "Oct": return 10;
                case "Nov": return 11;
                case "Dec": return 12;
            }
            return 0;
        }

        private string WeekDay(int i)
        {
            return new string[] { "?", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" }[i];
        }

        public string SayAirings
        {
            get
            {
                if (RunningShow)
                {
                    int h = m_AirHour % 12;
                    if (h == 0)
                        h = 12;
                    return String.Format("{0} at {1:00}:{2:00} {5} on {3} ({4} min)", SayWeekDays, h, m_AirMin, m_Network, m_Runtime, (m_AirHour >= 12 ? "PM" : "AM"));
                }
                else
                    return "TV Show no more on schedule";
            }
        }

        public string SayWeekDays
        {
            get
            {
                string s = "";
                for (int i = 0; i < m_Weekdays.Length; ++i)
                {
                    if (i > 0)
                        s += ", ";
                    s += WeekDay(m_Weekdays[i]);
                }
                return s;
            }
        }

        public string SayGenres
        {
            get
            {
                string s = "";
                for (int i = 0; i < m_Genres.Length; ++i)
                {
                    if (i > 0)
                        s += ", ";
                    s += m_Genres[i];
                }
                return s;
            }
        }

        public string MarshallGenres
        {
            get
            {
                string s = "";
                if (m_Genres != null)
                {
                    for (int i = 0; i < m_Genres.Length; ++i)
                    {
                        if (i > 0)
                            s += "|";
                        s += m_Genres[i];
                    }
                }
                return s;
            }
        }

        public string MarshallWeekDays
        {
            get
            {
                string s = "";
                for (int i = 0; i < m_Weekdays.Length; ++i)
                {
                    if (i > 0)
                        s += "|";
                    s += m_Weekdays[i];
                }
                return s;
            }
        }

    }
}
